﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Configuration;
using System.Net;
using System.Threading;
using IRC.NET.Commands;

namespace IRC.NET.Net
{
    public delegate void MessageRecievedEventHandler(object sender, MessageRecievedEventArgs args);

    public class IrcServerConnection : ServerConnectionBase
    {
        private static readonly string DEFAULT_PORT_KEY = "DefaultIrcPort";

        public event MessageRecievedEventHandler MessageRecieved;
        private IPAddress _address;
        private int _port;
        private Thread _worker;

        public IrcServerConnection(string connectionString)
        {
            if (String.IsNullOrEmpty(connectionString))
            {
                throw new ServerConnectionException("Connection string cannot be null!");
            }

            int port = -1;
            string domain = string.Empty;

            if (connectionString.LastIndexOf(':') < 0)
            {
                // Try to get the default connection string
                if (!string.IsNullOrEmpty(ConfigurationManager.AppSettings[DEFAULT_PORT_KEY]))
                {
                    port = Convert.ToInt32(ConfigurationManager.AppSettings[DEFAULT_PORT_KEY]);
                    domain = connectionString;
                }
                else
                {
                    throw new ConfigurationException("Unable to load default port.");
                }
            }
            else
            {
                int idx = connectionString.LastIndexOf(':') + 1;
                string portString = connectionString.Substring(idx, (connectionString.Length - idx));
                port = Convert.ToInt32(portString);

                idx--;
                connectionString.Substring(0, idx);
            }

            IPHostEntry entry = Dns.Resolve(domain);
            IPAddress address = entry.AddressList[0];
            this._address = address;
            this._port = port;
        }

        ~IrcServerConnection()
        {
            if (this._worker != null && this._worker.ThreadState != ThreadState.Stopped)
            {
                this._worker.Abort();
            }
        }

        public override void Close()
        {
            if (this._worker != null)
            {
                this._worker.Abort();
            }

            base.Close();
        }

        public void OpenConnection()
        {
            this.Connect(this._address, this._port);

            ThreadStart starter = new ThreadStart(this._ReadAsync);
            this._worker = new Thread(starter);
            this._worker.Start();
        }

        public void Send(string message)
        {
            base.Send(message);
        }

        public void SendCommand(ICommand command)
        {
            base.Send(command.ToString());
        }

        private void _ReadAsync()
        {
            while (true)
            {
                string message = base.Recieve();

                if (string.IsNullOrEmpty(message))
                {
                    Thread.Sleep(0);
                    continue;
                }

                this.OnMessageRecieved(new MessageRecievedEventArgs(message));
            }
        }

        protected void OnMessageRecieved(MessageRecievedEventArgs args)
        {
            if (this.MessageRecieved != null)
            {
                this.MessageRecieved(this, args);
            }
        }
    }
}
